home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src.arc / AX25.C < prev    next >
C/C++ Source or Header  |  1989-08-19  |  10KB  |  400 lines

  1. /* Low level AX.25 frame processing - address header */
  2.  
  3. #include <stdio.h>
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "iface.h"
  7. #include "timer.h"
  8. #include "arp.h"
  9. #include "slip.h"
  10. #include "ax25.h"
  11. #include "lapb.h"
  12. #include "netrom.h"
  13. #include "ip.h"
  14. #include <ctype.h>
  15.  
  16. static int axsend __ARGS((struct iface *iface,struct ax25_addr *dest,
  17.     struct ax25_addr *source,char cmdrsp,char ctl,struct mbuf *data));
  18. static int16 ax25rhash __ARGS((struct ax25_addr *s));
  19.  
  20. /* AX.25 broadcast address: "QST-0" in shifted ascii */
  21. static struct ax25_addr Ax25_bdcst = {
  22.     'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1,
  23.     ('0'<<1) | E,
  24. };
  25. static char Axbdcst[AXALEN];    /* Same thing, network format */
  26. struct ax25_addr Mycall;
  27. struct ax_route *Ax_routes[NAXROUTE];    /* Routing table header */
  28. int Digipeat = 1;    /* Controls digipeating */
  29.  
  30. /* Send IP datagrams across an AX.25 link */
  31. int
  32. ax_send(bp,iface,gateway,prec,del,tput,rel)
  33. struct mbuf *bp;
  34. struct iface *iface;
  35. int32 gateway;
  36. int prec;
  37. int del;
  38. int tput;
  39. int rel;
  40. {
  41.     char *hw_addr;
  42.     struct ax25_cb *axp;
  43.     struct ax25_addr destaddr;
  44.     struct mbuf *tbp;
  45.  
  46.     if((hw_addr = res_arp(iface,ARP_AX25,gateway,bp)) == NULLCHAR)
  47.         return 0;    /* Wait for address resolution */
  48.  
  49.     if(del || (!rel && (iface->flags == DATAGRAM_MODE))){
  50.         /* Use UI frame */
  51.         return (*iface->output)(iface,hw_addr,
  52.             iface->hwaddr,PID_IP,bp);
  53.     }
  54.     /* Reliability is needed; use I-frames in AX.25 connection */
  55.     memcpy(destaddr.call,hw_addr,ALEN);
  56.     destaddr.ssid = hw_addr[ALEN];
  57.  
  58.     if((axp = find_ax25(&destaddr)) == NULLAX25){
  59.         /* Open a new connection */
  60.         axp = open_ax25(iface,(struct ax25_addr *)iface->hwaddr,
  61.          (struct ax25_addr *)hw_addr,
  62.          AX_ACTIVE,Axwindow,s_arcall,s_atcall,s_ascall,-1);
  63.         if(axp == NULLAX25){
  64.             free_p(bp);
  65.             return -1;
  66.         }
  67.     }
  68.     if(axp->state == DISCONNECTED){
  69.         est_link(axp);
  70.         lapbstate(axp,SETUP);
  71.     }
  72.     /* Insert the PID */
  73.     if((tbp = pushdown(bp,1)) == NULLBUF){
  74.         free_p(bp);
  75.         return -1;
  76.     }
  77.     bp = tbp;
  78.     bp->data[0] = PID_IP;
  79.     if((tbp = segmenter(bp,axp->paclen)) == NULLBUF){
  80.         free(bp);
  81.         return -1;
  82.     }
  83.     return send_ax25(axp,tbp,-1);
  84. }
  85. /* Add AX.25 link header and send packet.
  86.  * Note that the calling order here must match enet_output
  87.  * since ARP also uses it.
  88.  */
  89. int
  90. ax_output(iface,dest,source,pid,data)
  91. struct iface *iface;    /* Interface to use; overrides routing table */
  92. char *dest;        /* Destination AX.25 address (7 bytes, shifted) */
  93. char *source;        /* Source AX.25 address (7 bytes, shifted) */
  94. int16 pid;        /* Protocol ID */
  95. struct mbuf *data;    /* Data field (follows PID) */
  96. {
  97.     struct mbuf *bp;
  98.  
  99.     /* Prepend pid to data */
  100.     bp = pushdown(data,1);
  101.     if(bp == NULLBUF){
  102.         free_p(data);
  103.         return -1;
  104.     }
  105.     bp->data[0] = (char)pid;
  106.     return axsend(iface,(struct ax25_addr *)dest,
  107.      (struct ax25_addr *)source,COMMAND,UI,bp);
  108. }
  109. /* Common subroutine for sendframe() and ax_output() */
  110. static int
  111. axsend(iface,dest,source,cmdrsp,ctl,data)
  112. struct iface *iface;    /* Interface to use; overrides routing table */
  113. struct ax25_addr *dest;    /* Destination AX.25 address (7 bytes, shifted) */
  114. struct ax25_addr *source;/* Source AX.25 address (7 bytes, shifted) */
  115. char cmdrsp;        /* Command/response indication */
  116. char ctl;        /* Control field */
  117. struct mbuf *data;    /* Data field (includes PID) */
  118. {
  119.     struct mbuf *cbp;
  120.     struct ax25 addr;
  121.     struct ax_route *axr;
  122.  
  123.     /* If there's a digipeater route, get it */
  124.     axr = ax_lookup((struct ax25_addr *)dest);
  125.  
  126.     memset((char *)&addr,0,sizeof(addr));
  127.     ASSIGN(addr.dest,*dest);
  128.     ASSIGN(addr.source,*source);
  129.     addr.cmdrsp = cmdrsp;
  130.  
  131.     if(axr != NULLAXR){
  132.         memcpy((char *)addr.digis,(char *)axr->digis,
  133.          axr->ndigis*sizeof(struct ax25_addr));
  134.         addr.ndigis = axr->ndigis;
  135.     } else
  136.         addr.ndigis = 0;
  137.  
  138.     /* Allocate mbuf for control field, and fill in */
  139.     if((cbp = pushdown(data,1)) == NULLBUF){
  140.         free_p(data);
  141.         return -1;
  142.     }
  143.     cbp->data[0] = ctl;
  144.  
  145.     if((data = htonax25(&addr,cbp)) == NULLBUF){
  146.         free_p(cbp);    /* Also frees data */
  147.         return -1;
  148.     }
  149.     /* This shouldn't be necessary because redirection has already been
  150.      * done at the IP router layer, but just to be safe...
  151.      */
  152.     if(iface->forw != NULLIF)
  153.         return (*iface->forw->raw)(iface->forw,data);
  154.     else
  155.         return (*iface->raw)(iface,data);
  156. }
  157. /* Process incoming AX.25 packets.
  158.  * After optional tracing, the address field is examined. If it is
  159.  * directed to us as a digipeater, repeat it.  If it is addressed to
  160.  * us or to QST-0, kick it upstairs depending on the protocol ID.
  161.  */
  162. void
  163. ax_recv(iface,bp)
  164. struct iface *iface;
  165. struct mbuf *bp;
  166. {
  167.     struct ax25_addr *ap;
  168.     struct mbuf *hbp;
  169.     char control;
  170.     struct ax25 hdr;
  171.     struct ax25_cb *axp;
  172.     struct ax25_addr ifcall;
  173.     struct ax_route *axr;
  174.  
  175.     /* Use the address associated with this iface */
  176.     memcpy(ifcall.call,iface->hwaddr,ALEN);
  177.     ifcall.ssid = iface->hwaddr[ALEN];
  178.  
  179.     /* Pull header off packet and convert to host structure */
  180.     if(ntohax25(&hdr,&bp) < 0){
  181.         /* Something wrong with the header */
  182.         free_p(bp);
  183.         return;
  184.     }
  185.     /* Scan, looking for our call in the repeater fields, if any.
  186.      * Repeat appropriate packets.
  187.      */
  188.     for(ap = &hdr.digis[0]; ap < &hdr.digis[hdr.ndigis]; ap++){
  189.         if(ap->ssid & REPEATED)
  190.             continue;    /* Already repeated */
  191.         /* Check if packet is directed to us as a digipeater */
  192.         if(Digipeat && addreq(ap,&ifcall)){
  193.             /* Yes, kick it back out */
  194.             ap->ssid |= REPEATED;
  195.             if((hbp = htonax25(&hdr,bp)) != NULLBUF){
  196.                 if(iface->forw != NULLIF)
  197.                     (*iface->forw->raw)(iface->forw,hbp);
  198.                 else
  199.                     (*iface->raw)(iface,hbp);
  200.                 bp = NULLBUF;
  201.             }
  202.         }
  203.         free_p(bp);    /* Dispose if not forwarded */
  204.         return;
  205.     }
  206.     if(bp == NULLBUF){
  207.         /* Nothing left */
  208.         return;
  209.     }
  210.     /* Sneak a peek at the control field. This kludge is necessary because
  211.      * AX.25 lacks a proper protocol ID field between the address and LAPB
  212.      * sublayers; a control value of UI indicates that LAPB is to be
  213.      * bypassed.
  214.      */
  215.     control = *bp->data & ~PF;
  216.     if(uchar(control) == UI){
  217.         char pid;
  218.  
  219.         (void) pullchar(&bp);
  220.         if(pullup(&bp,&pid,1) != 1)
  221.             return;        /* No PID */
  222.         /* Handle packets. Multi-frame messages are not allowed */
  223.         switch(uchar(pid)){
  224.         case PID_IP:
  225.             if(addreq(&hdr.dest,&Ax25_bdcst))
  226.                 ip_route(bp,1);    /* Broadcast packet */
  227.             else if(addreq(&hdr.dest,&ifcall))
  228.                 ip_route(bp,0);    /* Packet directed at us */
  229.             else free_p(bp);
  230.             break;
  231.         case PID_ARP:
  232.             if(addreq(&hdr.dest,&ifcall)
  233.                || addreq(&hdr.dest,&Ax25_bdcst))
  234.                 arp_input(iface,bp);
  235.             else free_p(bp);
  236.             break;
  237.         case PID_NETROM:
  238.             if(addreq(&hdr.dest,&Nr_nodebc))
  239.                 nr_nodercv(iface,&hdr.source,bp);
  240.             else free_p(bp);
  241.             break;
  242.         case PID_NO_L3:
  243.             if(addreq(&hdr.dest,&ifcall))
  244.                 beac_input(iface,&hdr.source,bp);
  245.             else free_p(bp);
  246.             break;
  247.         default:
  248.             free_p(bp);
  249.             break;
  250.         }
  251.         return;
  252.     }
  253.     /* Everything from here down is LAPB, so drop anything that's
  254.      * not explicitly for us ...
  255.      */
  256.     if(!addreq(&hdr.dest,&ifcall)){
  257.         free_p(bp) ;
  258.         return ;
  259.     }
  260.     /* If there's no locally-set entry in the routing table,
  261.      * enter or update it. Leave local routes alone.
  262.      */
  263.     if((axr = ax_lookup(&hdr.source)) == NULLAXR || axr->type == AX_AUTO){
  264.         struct ax25_addr digis[MAXDIGIS];
  265.  
  266.         if(hdr.ndigis > 0){
  267.             int i,j;
  268.             /* Construct reverse digipeater path */
  269.             for(i=hdr.ndigis-1,j=0;i >= 0;i--,j++){
  270.                 memcpy((char *)&digis[j],(char *)&hdr.digis[i],
  271.                     sizeof(struct ax25_addr));
  272.                 digis[j].ssid &= ~(E|REPEATED);
  273.             }
  274.         }
  275.         ax_add(&hdr.source,AX_AUTO,digis,hdr.ndigis);
  276.     }
  277.     /* Find the source address in hash table */
  278.     if((axp = find_ax25(&hdr.source)) == NULLAX25){
  279.         /* Create a new ax25 entry for this guy,
  280.          * insert into hash table keyed on his address,
  281.          * and initialize table entries
  282.          */
  283.         if((axp = cr_ax25(&hdr.source)) == NULLAX25){
  284.             free_p(bp);
  285.             return;
  286.         }
  287.         /* Swap source and destination */
  288.         ASSIGN(axp->remote,hdr.source);
  289.         ASSIGN(axp->local,hdr.dest);
  290.         axp->iface = iface;
  291.     }
  292.     if(hdr.cmdrsp == UNKNOWN)
  293.         axp->proto = V1;    /* Old protocol in use */
  294.  
  295.     lapb_input(axp,hdr.cmdrsp,bp);
  296. }
  297. /* General purpose AX.25 frame output */
  298. int
  299. sendframe(axp,cmdrsp,ctl,data)
  300. struct ax25_cb *axp;
  301. int cmdrsp;
  302. int ctl;
  303. struct mbuf *data;
  304. {
  305.     return axsend(axp->iface,&axp->remote,&axp->local,cmdrsp,ctl,data);
  306. }
  307. void
  308. axarp()
  309. {
  310.     memcpy(Axbdcst,Ax25_bdcst.call,ALEN);
  311.     Axbdcst[ALEN] = Ax25_bdcst.ssid;
  312.  
  313.     arp_init(ARP_AX25,AXALEN,PID_IP,PID_ARP,10,Axbdcst,psax25,setpath);
  314. }
  315. /* Find a route for an AX.25 address */
  316. struct ax_route *
  317. ax_lookup(target)
  318. struct ax25_addr *target;
  319. {
  320.     register struct ax_route *axr;
  321.  
  322.     for(axr = Ax_routes[ax25rhash(target)]; axr != NULLAXR; axr = axr->next){
  323.         if(addreq(&axr->target,target))
  324.             break;
  325.     }
  326.     return axr;
  327. }
  328. /* Add an entry to the AX.25 routing table */
  329. struct ax_route *
  330. ax_add(target,type,digis,ndigis)
  331. struct ax25_addr *target;
  332. int type;
  333. struct ax25_addr digis[];
  334. int ndigis;
  335. {
  336.     int16 hval,i;
  337.     register struct ax_route *axr;
  338.  
  339.     if(ndigis < 0 || ndigis > MAXDIGIS)
  340.         return NULLAXR;
  341.  
  342.     if((axr = ax_lookup(target)) == NULLAXR){
  343.         axr = (struct ax_route *)calloc(1,sizeof(struct ax_route));
  344.         if(axr == NULLAXR)
  345.             return NULLAXR;
  346.         hval = ax25rhash(target);
  347.         axr->prev = NULLAXR;
  348.         axr->next = Ax_routes[hval];
  349.         if(axr->next != NULLAXR)
  350.             axr->next->prev = axr;
  351.         Ax_routes[hval] = axr;
  352.         ASSIGN(axr->target,*target);
  353.         axr->ndigis = ndigis;
  354.     }
  355.     axr->type = type;
  356.     if(axr->ndigis != ndigis)
  357.         axr->ndigis = ndigis;
  358.  
  359.     for(i=0;i<ndigis;i++)
  360.         memcpy((char *)axr->digis,(char *)digis,
  361.          ndigis*sizeof(struct ax25_addr));
  362.     return axr;
  363. }
  364. int
  365. ax_drop(target)
  366. struct ax25_addr *target;
  367. {
  368.     register struct ax_route *axr;
  369.  
  370.     if((axr = ax_lookup(target)) == NULLAXR)
  371.         return -1;
  372.  
  373.     if(axr->next != NULLAXR)
  374.         axr->next->prev = axr->prev;
  375.     if(axr->prev != NULLAXR)
  376.         axr->prev->next = axr->next;
  377.     else
  378.         Ax_routes[ax25rhash(target)] = axr->next;
  379.     free((char *)axr);
  380.     return 0;
  381. }
  382. /* Address hash function. Exclusive-ORs each byte, ignoring
  383.  * such insignificant, annoying things as E and H bits
  384.  */
  385. static int16
  386. ax25rhash(s)
  387. struct ax25_addr *s;
  388. {
  389.     register char x;
  390.     register int i;
  391.     register char *cp;
  392.  
  393.     x = 0;
  394.     cp = s->call;
  395.     for(i=ALEN; i!=0; i--)
  396.         x ^= *cp++ & 0xfe;
  397.     x ^= s->ssid & SSID;
  398.     return uchar(x) % NAXROUTE;
  399. }
  400.